{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "660ce795-9307-4c2c-98a1-beabcb36c740",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/langchain-ai/langchain-academy/blob/main/module-0/basics.ipynb) [![Open in LangChain Academy](https://cdn.prod.website-files.com/65b8cd72835ceeacd4449a53/66e9eba12c7b7688aa3dbb5e_LCA-badge-green.svg)](https://academy.langchain.com/courses/take/intro-to-langgraph/lessons/56295530-getting-set-up-video-guide)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef597741-3211-4ecc-92f7-f58023ee237e",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# LangChain Academy\n",
    "\n",
    "Welcome to LangChain Academy! \n",
    "\n",
    "## Context\n",
    "\n",
    "At LangChain, we aim to make it easy to build LLM applications. One type of LLM application you can build is an agent. There’s a lot of excitement around building agents because they can automate a wide range of tasks that were previously impossible. \n",
    "\n",
    "In practice though, it is incredibly difficult to build systems that reliably execute on these tasks. As we’ve worked with our users to put agents into production, we’ve learned that more control is often necessary. You might need an agent to always call a specific tool first or use different prompts based on its state. \n",
    "\n",
    "To tackle this problem, we’ve built [LangGraph](https://docs.langchain.com/oss/python/langgraph/overview) — a framework for building agent and multi-agent applications. Separate from the LangChain package, LangGraph’s core design philosophy is to help developers add better precision and control into agent workflows, suitable for the complexity of real-world systems.\n",
    "\n",
    "## Course Structure\n",
    "\n",
    "The course is structured as a set of modules, with each module focused on a particular theme related to LangGraph. You will see a folder for each module, which contains a series of notebooks. A video will accompany each notebook to help walk through the concepts, but the notebooks are also stand-alone, meaning that they contain explanations and can be viewed independently of the videos. Each module folder also contains a `studio` folder, which contains a set of graphs that can be loaded into [LangSmith Studio](https://docs.langchain.com/langsmith/quick-start-studio), our IDE for building LangGraph applications.\n",
    "\n",
    "## Setup\n",
    "\n",
    "Before you begin, please follow the instructions in the `README` to create an environment and install dependencies.\n",
    "\n",
    "## Chat models\n",
    "\n",
    "In this course, we'll use Chat Models, which take a sequence of messages as input and return messages as output. LangChain supports many models via [third-party integrations](https://docs.langchain.com/oss/python/integrations/chat). By default, the course will use  [ChatOpenAI](https://docs.langchain.com/oss/python/integrations/chat/openai) because it is both popular and performant. As noted, please ensure that you have an `OPENAI_API_KEY`.\n",
    "\n",
    "Let's check that your `OPENAI_API_KEY` is set and, if not, you will be asked to enter it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0f9a52c8",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#%%capture --no-stderr\n",
    "#%pip install --quiet -U langchain_openai langchain_core langchain_community langchain-tavily\n",
    "\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "# load_dotenv(find_dotenv(usecwd=True))\n",
    "load_dotenv(override=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c2a15227",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os, getpass\n",
    "\n",
    "def _set_env(var: str):\n",
    "    if not os.environ.get(var):\n",
    "        os.environ[var] = getpass.getpass(f\"{var}: \")\n",
    "\n",
    "_set_env(\"OPENAI_API_KEY\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a326f35b",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "[Here](https://docs.langchain.com/oss/python/langchain/models) is a useful how-to for all the things that you can do with chat models, but we'll show a few highlights below. If you've run `pip install -r requirements.txt` as noted in the README, then you've installed the `langchain-openai` package. With this, we can instantiate our `ChatOpenAI` model object. You can see pricing for various models [here](https://openai.com/api/pricing/). The notebooks will default to `gpt-4o` because it offers a good balance of quality, price, and speed, but you can also opt for the lower-priced `gpt-3.5` series or more recent models.\n",
    "\n",
    "There are [a few standard parameters](https://docs.langchain.com/oss/python/langchain/models#parameters) that we can set with chat models. Two of the most common are:\n",
    "\n",
    "* `model`: the name of the model\n",
    "* `temperature`: the sampling temperature\n",
    "\n",
    "`Temperature` controls the randomness or creativity of the model's output where low temperature (close to 0) is more deterministic and focused outputs. This is good for tasks requiring accuracy or factual responses. High temperature (close to 1) is good for creative tasks or generating varied responses. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e19a54d3",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "gpt4o_chat = ChatOpenAI(model=\"kimi-latest\", temperature=0)\n",
    "gpt35_chat = ChatOpenAI(model=\"kimi-k2-turbo-preview\", temperature=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28450d1b",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "Chat models in LangChain have a number of [default methods](https://reference.langchain.com/python/langchain_core/runnables). For the most part, we'll be using:\n",
    "\n",
    "* [stream](https://docs.langchain.com/oss/python/langchain/models#stream): stream back chunks of the response\n",
    "* [invoke](https://docs.langchain.com/oss/python/langchain/models#invoke): call the chain on an input\n",
    "\n",
    "And, as mentioned, chat models take [messages](https://docs.langchain.com/oss/python/langchain/messages) as input. Messages have a role (that describes who is saying the message) and a content property. We'll be talking a lot more about this later, but here let's just show the basics."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b1280e1b",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='Hello! How can I assist you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 10, 'total_tokens': 20, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_provider': 'openai', 'model_name': 'kimi-latest-8k', 'system_fingerprint': None, 'id': 'chatcmpl-6933a4f4f35eb5a8a08878b0', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019af1bc-4b2b-7323-8557-612c05a2facb-0', usage_metadata={'input_tokens': 10, 'output_tokens': 10, 'total_tokens': 20, 'input_token_details': {}, 'output_token_details': {}})"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.messages import HumanMessage\n",
    "\n",
    "# Create a message\n",
    "msg = HumanMessage(content=\"Hello world\", name=\"Lance\")\n",
    "\n",
    "# Message list\n",
    "messages = [msg]\n",
    "\n",
    "# Invoke the model with a list of messages \n",
    "gpt4o_chat.invoke(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cac73e4c",
   "metadata": {},
   "source": [
    "We get an `AIMessage` response. Also, note that we can just invoke a chat model with a string. When a string is passed in as input, it is converted to a `HumanMessage` and then passed to the underlying model.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f27c6c9a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='Hello! How can I assist you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 9, 'total_tokens': 19, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_provider': 'openai', 'model_name': 'kimi-latest-8k', 'system_fingerprint': None, 'id': 'chatcmpl-6933a5115fc21a74db5a54d3', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019af1bc-bd7f-78f0-8892-79d8df1c3807-0', usage_metadata={'input_tokens': 9, 'output_tokens': 10, 'total_tokens': 19, 'input_token_details': {}, 'output_token_details': {}})"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gpt4o_chat.invoke(\"hello world\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "fdc2f0ca",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='Hello! How can I help you today?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 9, 'total_tokens': 19, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_provider': 'openai', 'model_name': 'kimi-k2-turbo-preview', 'system_fingerprint': None, 'id': 'chatcmpl-6933a515dc9b7b119b059da8', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019af1bc-ca4e-7173-9675-5fdbe99ac149-0', usage_metadata={'input_tokens': 9, 'output_tokens': 10, 'total_tokens': 19, 'input_token_details': {}, 'output_token_details': {}})"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gpt35_chat.invoke(\"hello world\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "582c0e5a",
   "metadata": {},
   "source": [
    "The interface is consistent across all chat models and models are typically initialized once at the start up each notebooks. \n",
    "\n",
    "So, you can easily switch between models without changing the downstream code if you have strong preference for another provider.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ad0069a",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "## Search Tools\n",
    "\n",
    "You'll also see [Tavily](https://tavily.com/) in the README, which is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results. As mentioned, it's easy to sign up and offers a generous free tier. Some lessons (in Module 4) will use Tavily by default but, of course, other search tools can be used if you want to modify the code for yourself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "091dff13",
   "metadata": {},
   "outputs": [],
   "source": [
    "_set_env(\"TAVILY_API_KEY\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "52d69da9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_tavily import TavilySearch  # updated at 1.0\n",
    "\n",
    "tavily_search = TavilySearch(max_results=3)\n",
    "\n",
    "data = tavily_search.invoke({\"query\": \"What is LangGraph?\"})\n",
    "search_docs = data.get(\"results\", data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d06f87e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'url': 'https://www.datacamp.com/tutorial/langgraph-tutorial',\n",
       "  'title': 'LangGraph Tutorial: What Is LangGraph and How to Use It?',\n",
       "  'content': 'LangGraph is a library within the LangChain ecosystem that provides a framework for defining, coordinating, and executing multiple LLM agents (or chains) in a structured and efficient manner. By managing the flow of data and the sequence of operations, LangGraph allows developers to focus on the high-level logic of their applications rather than the intricacies of agent coordination. Whether you need a chatbot that can handle various types of user requests or a multi-agent system that performs complex tasks, LangGraph provides the tools to build exactly what you need. LangGraph significantly simplifies the development of complex LLM applications by providing a structured framework for managing state and coordinating agent interactions.',\n",
       "  'score': 0.9999697,\n",
       "  'raw_content': None},\n",
       " {'url': 'https://www.shakudo.io/integrations/langgraph',\n",
       "  'title': 'What is LangGraph? Docs, Demo and How to Deploy - Shakudo',\n",
       "  'content': 'LangGraph is a framework for building stateful, multi-agent applications using large language models (LLMs). It extends the LangChain',\n",
       "  'score': 0.99995804,\n",
       "  'raw_content': None},\n",
       " {'url': 'https://docs.langchain.com/oss/javascript/langgraph/overview',\n",
       "  'title': 'LangGraph overview - Docs by LangChain',\n",
       "  'content': 'Trusted by companies shaping the future of agents— including Klarna, Replit, Elastic, and more— LangGraph is a low-level orchestration framework and runtime for building, managing, and deploying long-running, stateful agents. Before using LangGraph, we recommend you familiarize yourself with some of the components used to build agents, starting with models and tools. If you are just getting started with agents or want a higher-level abstraction, we recommend you use LangChain’s agents that provide pre-built architectures for common LLM and tool-calling loops. LangGraph is focused on the underlying capabilities important for agent orchestration: durable execution, streaming, human-in-the-loop, and more. LangGraph provides low-level supporting infrastructure for *any* long-running, stateful workflow or agent. While LangGraph can be used standalone, it also integrates seamlessly with any LangChain product, giving developers a full suite of tools for building agents. Prototype locally with LangGraph, then move to production with integrated observability and evaluation to build more reliable agent systems.## LangGraph. Contains agent abstractions built on top of LangGraph.',\n",
       "  'score': 0.9999502,\n",
       "  'raw_content': None}]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "search_docs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a7545f4-aeb7-4b03-91f5-df3e021fe960",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
